<?php

namespace tmcore\services\crud;

use tmcore\exceptions\CrudException;
use tmcore\services\crud\generators\Controller;
use tmcore\services\crud\generators\Model;
use tmcore\services\crud\generators\Route;
use tmcore\services\crud\generators\Service;
use tmcore\services\crud\generators\Sql;
use tmcore\services\crud\generators\Validate;
use tmcore\services\crud\generators\VueApi;
use tmcore\services\crud\generators\VueIndexView;
use tmcore\services\crud\generators\VueEditView;
use tmcore\services\crud\generators\VueDetailView;
use tmcore\utils\File;
use tmcore\utils\Helper;

class CrudService
{
    /**
     * 生成文件路径
     * @var string
     */
    protected string $crudPath;

    /**
     * 压缩状态
     * @var bool
     */
    protected bool $zipStatus = false;

    /**
     * 压缩文件名称
     * @var string
     */
    protected string $zipFileName;

    /**
     * 导出文件唯一标识
     * @var string
     */
    private string $identifier = '';

    /**
     * 初始化
     */
    public function __construct()
    {
        $this->crudPath = root_path() . 'data/crud/';
        $this->zipFileName = 'crud_' . date('YmdHis') . '.zip';
        $this->identifier = md5(date('YmdHis') . '_' . Helper::get_random(6, '0123456789'));
    }

    /**
     * 清空生成文件
     */
    public function clearCrudDirFile()
    {
        UtilService::checkDir($this->crudPath);
        File::del_dir($this->crudPath);
    }

    /**
     * 获取压缩状态
     * @return bool
     */
    public function getZipStatus() {
        return $this->zipStatus;
    }

    /**
     * 设置压缩状态
     * @param $value
     * @return CrudService
     */
    public function setZipStatus($value) {
        $this->zipStatus = $value?true:false;
        return $this;
    }

    /**
     * 生成器相关类
     * @param $tableData
     * @return string[]
     */
    public function getGeneratorClass($tableData)
    {
        $data = [
            Controller::class,
            Service::class,
            Validate::class,
            Model::class,
            Route::class,
            Sql::class,
            VueApi::class,
            VueIndexView::class,
        ];

        if($tableData['is_insert'] || $tableData['is_update']) array_push($data, VueEditView::class);
        if($tableData['is_detail']) array_push($data, VueDetailView::class);

        return $data;
    }

    /**
     * 预览文件
     * @param array $tableData
     * @return array
     */
    public function preview(array $tableData)
    {
        $data = [];
        foreach ($this->getGeneratorClass($tableData) as $item) {
            $generator = app()->make($item);
            $generator->initData($tableData);
            $data[] = $generator->getFileInfo();
        }
        return $data;
    }

    /**
     * 生成文件
     * @param array $tableData
     */
    public function generate(array $tableData)
    {
        foreach ($this->getGeneratorClass($tableData) as $item) {
            $generator = app()->make($item);
            $generator->initData($tableData);
            $generator->generate();
            // 是否压缩包下载
            if ($generator->isTypeZip()) {
                $this->setZipStatus(true);
            }
            // 是否构建菜单
            if ($item == 'tmcore\services\crud\generators\Sql' && $generator->isBuildMenu()) {
                $generator->buildMenuSql();
            }
            // 是否生成excel示例文件
            if ($item == 'tmcore\services\crud\generators\Service' && $tableData['is_import']) {
                $generator->createExcelTemplate();
            }
        }
    }

    /**
     * 压缩文件
     * @return bool|array
     * @throws CrudException
     */
    public function zipFile()
    {
        if(!$this->getZipStatus()) return false;

        $filePath = $this->crudPath . $this->zipFileName;

        $res = File::zip(root_path() . 'data/crud', $filePath, false);
        if($res === false) throw new CrudException(File::getError());

        return ['url' => 'data/crud/' . $this->zipFileName, 'name' => $this->zipFileName, 'identifier' => $this->identifier];
    }
}